package com.beiding.objectanalyzer;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ObjectUtils {

    public static Integer idForObject(Object object) {
        object.getClass();
        return System.identityHashCode(object);
    }


    public static KeyNode createKeyNode(Object object) {
        KeyNode keyNode = new KeyNode();
        keyNode.setValue(object);
        Class<?> objectClass = object.getClass();
        keyNode.setType(objectClass);
        return keyNode;
    }

    /*
        创建数组元素
     */
    public static KeyNode createArrayComponent(Object[] from, int index, int layer) {
        Object object = from[index];
        if (object == null) {
            return null;
        }
        KeyNode keyNode = createKeyNode(object);
        keyNode.setHolder(from);
        keyNode.setLayer(layer);
        keyNode.setIndex(index);
        return keyNode;
    }

    public static KeyNode createFieldKeyNode(Object from, Field field, int layer) {

        field.setAccessible(true);

        Object object = null;

        try {
            object = field.get(from);
        } catch (IllegalAccessException ignore) {
        }
        if (object == null) {
            return null;
        }

        KeyNode keyNode = createKeyNode(object);

        keyNode.setField(field);

        keyNode.setValue(object);

        keyNode.setLayer(layer);

        keyNode.setType(field.getType());

        keyNode.setHolder(from);

        return keyNode;
    }

    public static List<AnalyzeKey> deepAnalyzeKey(Object object) {
        List<AnalyzeKey> analyzeKeys = new ArrayList<>();
        KeyNode keyNode = new KeyNode();
        keyNode.setValue(object);
        keyNode.setLayer(0);
        keyNode.setRoot(true);

        keyNode.setType(object.getClass());
        List<KeyNode> all = new ArrayList<>();
        System.out.println(all.size());

        deepKeyNode(keyNode, all);
        all.forEach(n -> {
            AnalyzeKey analyzeKey = new AnalyzeKey();
            analyzeKey.setEndNode(n);
            analyzeKeys.add(analyzeKey);
        });

        return analyzeKeys;
    }

    private static Set<Object> objects = new HashSet<>();


    private static void deepKeyNode(KeyNode parent, List<KeyNode> all) {

        Object object = parent.getValue();
        Class<?> objectClass = object.getClass();
        int layer = parent.getLayer() + 1;

        //如果父节点是个数组

        if (parent.isArray()) {

            //如果数组元素是对象类型就深入,如果不是对象类型的就直接跳过
            if (parent.componentIsObject()) {

                Object[] objs = (Object[]) object;

                if (objs.length > 0) {

                    for (int i = 0; i < objs.length; i++) {

                        KeyNode arrayComponent = createArrayComponent(objs, i, layer);

                        if (arrayComponent == null) {
                            continue;
                        }

                        arrayComponent.setHolderNode(parent);
                        all.add(arrayComponent);
                        System.out.println(all.size());
                        if (!arrayComponent.isLoop()) {
                            if (arrayComponent.isObject()) {
                                if (!arrayComponent.isTypeAbout()) {
                                    deepKeyNode(arrayComponent, all);
                                }
                            }
                        }

                    }

                }
            }

        } else {//父节点是对象

            while (objectClass != Object.class) {
                for (Field field : objectClass.getDeclaredFields()) {
                    KeyNode keyNode = createFieldKeyNode(object, field, layer);

                    if (keyNode != null) {
                        keyNode.setHolderNode(parent);
                        all.add(keyNode);

                        AnalyzeKey key = new AnalyzeKey();

                        key.setEndNode(keyNode);

                        String s = key.toString();

                        if (objects.contains(s)) {
                            System.out.println("存在:" + s);
                        } else {
                            System.out.println("新增:" + s);
                        }

                        objects.add(s);
                        if (!keyNode.isLoop()) {
                            if (keyNode.isObject()) {
                                if (!keyNode.isTypeAbout()) {
                                    //深度递归对象
                                    deepKeyNode(keyNode, all);
                                }
                            }
                        }
                    }
                }
                objectClass = objectClass.getSuperclass();
            }
        }
    }



    public static void main(String[] args) {

        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();

        ScriptEngine js = scriptEngineManager.getEngineByName("js");

        for (AnalyzeKey analyzeKey : deepAnalyzeKey(js)) {
            System.out.println(analyzeKey);
        }

    /*    KeyNode keyNode = new KeyNode();
        keyNode.setRoot(true);
        keyNode.setType(B.class);

        Set<KeyNode> keyNodes = new HashSet<>();
        keyNodes.add(keyNode);
        keyNode = new KeyNode();
        keyNode.setRoot(false);
        keyNode.setType(B.class);*/

        //   System.out.println(keyNodes.contains(keyNode));

    }


}

